﻿namespace ReplayDataFile
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Runtime.InteropServices;

    public class TimeSegmentList : IEnumerable<TimeSegment>, IEnumerable
    {
        private List<TimeSegment> segList;

        public TimeSegmentList()
        {
            this.segList = new List<TimeSegment>();
        }

        public TimeSegmentList(ICollection<TimeSegment> segList)
        {
            this.segList = new List<TimeSegment>(segList);
        }

        public TimeSegmentList ClipSegment(TimeSegment startSeg, DateTime startTime, TimeSpan clipTimeLen)
        {
            List<TimeSegment> segList = new List<TimeSegment>();
            TimeSpan span = new TimeSpan();
            TimeSegment segment = null;
            for (int i = this.segList.IndexOf(startSeg); i < this.segList.Count; i++)
            {
                TimeSegment segment3;
                if (i < 0)
                {
                    break;
                }
                TimeSegment segment2 = this.segList[i];
                if (segment == null)
                {
                    segment3 = new TimeSegment();
                    if (startTime <= segment2.EndTime)
                    {
                        TimeSpan span2 = (TimeSpan) (segment2.EndTime - startTime);
                        segment3.BeginTime = startTime;
                        segment3.EndTime = (span2 <= clipTimeLen) ? segment2.EndTime : (startTime + clipTimeLen);
                        segment3.BeginRecordNo = segment2.BeginRecordNo;
                        segment3.EndRecordNo = segment2.EndRecordNo;
                    }
                    else
                    {
                        segment3.BeginTime = startTime;
                        segment3.EndTime = startTime;
                        segment3.BeginRecordNo = segment3.EndRecordNo = -1L;
                    }
                    segList.Add(segment3);
                    span += segment3.Length;
                    segment = segment3;
                }
                else
                {
                    TimeSpan timeGapLength = GetTimeGapLength(segment.EndTime, segment2.BeginTime);
                    if ((span + timeGapLength) >= clipTimeLen)
                    {
                        segment3 = new TimeSegment {
                            BeginTime = segment.EndTime,
                            EndTime = segment.EndTime + (clipTimeLen - span),
                            BeginRecordNo = segment.EndRecordNo,
                            EndRecordNo = segment2.BeginRecordNo
                        };
                        segList.Add(segment3);
                        break;
                    }
                    span += timeGapLength;
                    if ((span + segment2.Length) >= clipTimeLen)
                    {
                        segment3 = segment2.Clone();
                        segment3.EndTime = segment2.BeginTime + (clipTimeLen - span);
                        segList.Add(segment3);
                        break;
                    }
                    segment3 = segment2.Clone();
                    segList.Add(segment3);
                    segment = segment3;
                    span += segment2.Length;
                }
                if (span >= clipTimeLen)
                {
                    break;
                }
            }
            return new TimeSegmentList(segList);
        }

        public DateTime GetBeginTime()
        {
            if ((this.segList == null) || (this.segList.Count == 0))
            {
                return DateTime.MinValue;
            }
            return this.segList[0].BeginTime;
        }

        public ICollection<DateTime> GetDayList()
        {
            Dictionary<DateTime, DateTime> dictionary = new Dictionary<DateTime, DateTime>();
            foreach (TimeSegment segment in this.segList)
            {
                bool flag;
                if ((segment.BeginTime == DateTime.MinValue) || (segment.EndTime == DateTime.MinValue))
                {
                    continue;
                }
                DateTime date = segment.BeginTime.Date;
                goto Label_00A5;
            Label_0065:
                if (!dictionary.ContainsKey(date))
                {
                    dictionary.Add(date, date);
                }
                date = date.AddDays(1.0);
                if (date > segment.EndTime)
                {
                    continue;
                }
            Label_00A5:
                flag = true;
                goto Label_0065;
            }
            return dictionary.Values;
        }

        public DateTime GetEndTime()
        {
            if ((this.segList == null) || (this.segList.Count == 0))
            {
                return DateTime.MinValue;
            }
            return this.segList[this.segList.Count - 1].EndTime;
        }

        public IEnumerator<TimeSegment> GetEnumerator()
        {
            return this.segList.GetEnumerator();
        }

        public TimeSegment GetFirstTimeSegment(DateTime time)
        {
            TimeSegment[] timeSegment = this.GetTimeSegment(time);
            if ((timeSegment == null) || (timeSegment.Length == 0))
            {
                return null;
            }
            return timeSegment[0];
        }

        public DateTime GetMaxTime()
        {
            if ((this.segList == null) || (this.segList.Count == 0))
            {
                return DateTime.MinValue;
            }
            DateTime minValue = DateTime.MinValue;
            foreach (TimeSegment segment in this.segList)
            {
                if (segment.EndTime > minValue)
                {
                    minValue = segment.EndTime;
                }
            }
            return minValue;
        }

        public DateTime GetMinTime()
        {
            if ((this.segList == null) || (this.segList.Count == 0))
            {
                return DateTime.MinValue;
            }
            DateTime maxValue = DateTime.MaxValue;
            foreach (TimeSegment segment in this.segList)
            {
                if (segment.BeginTime < maxValue)
                {
                    maxValue = segment.BeginTime;
                }
            }
            return ((maxValue == DateTime.MaxValue) ? DateTime.MinValue : maxValue);
        }

        public ICollection<DateTime> GetMonthList()
        {
            Dictionary<DateTime, DateTime> dictionary = new Dictionary<DateTime, DateTime>();
            foreach (DateTime time in this.GetDayList())
            {
                DateTime key = new DateTime(time.Year, time.Month, 1);
                if (!dictionary.ContainsKey(key))
                {
                    dictionary.Add(key, key);
                }
            }
            return dictionary.Values;
        }

        private static TimeSpan GetTimeGapLength(DateTime beginTime, DateTime endTime)
        {
            TimeSpan span = (TimeSpan) (endTime - beginTime);
            return ((span.Ticks >= 0L) ? span : new TimeSpan(0L));
        }

        public TimeSegment[] GetTimeSegment(DateTime time)
        {
            if (this.segList.Count != 0)
            {
                if (time < this.segList[0].BeginTime)
                {
                    return new TimeSegment[] { this.segList[0] };
                }
                if (time > this.segList[this.segList.Count - 1].EndTime)
                {
                    return new TimeSegment[] { this.segList[this.segList.Count - 1] };
                }
                TimeSegment segment = null;
                foreach (TimeSegment segment2 in this.segList)
                {
                    if ((segment != null) && ((time >= segment.EndTime) && (time < segment2.BeginTime)))
                    {
                        return new TimeSegment[] { segment, segment2 };
                    }
                    if ((time >= segment2.BeginTime) && (time < segment2.EndTime))
                    {
                        return new TimeSegment[] { segment2 };
                    }
                    segment = segment2;
                }
            }
            return null;
        }

        public TimeSegment[] GetTimeSegment(long recNo)
        {
            if (this.Count != 0)
            {
                if (recNo < this.segList[0].BeginRecordNo)
                {
                    return new TimeSegment[] { this.segList[0] };
                }
                if (recNo > this.segList[this.segList.Count - 1].EndRecordNo)
                {
                    return new TimeSegment[] { this.segList[this.segList.Count - 1] };
                }
                TimeSegment segment = null;
                foreach (TimeSegment segment2 in this.segList)
                {
                    if ((segment != null) && ((recNo >= segment.EndRecordNo) && (recNo < segment2.BeginRecordNo)))
                    {
                        return new TimeSegment[] { segment, segment2 };
                    }
                    if ((recNo >= segment2.BeginRecordNo) && (recNo < segment2.EndRecordNo))
                    {
                        return new TimeSegment[] { segment2 };
                    }
                    segment = segment2;
                }
            }
            return null;
        }

        public TimeSpan GetTotalTimeLen()
        {
            if (this.segList == null)
            {
                return new TimeSpan();
            }
            TimeSpan span = new TimeSpan();
            TimeSegment segment = null;
            foreach (TimeSegment segment2 in this.segList)
            {
                if (segment != null)
                {
                    TimeSpan span2 = (TimeSpan) (segment2.BeginTime - segment.EndTime);
                    if (span2.Ticks > 0L)
                    {
                        span += span2;
                    }
                }
                span += segment2.Length;
                segment = segment2;
            }
            return span;
        }

        public static TimeSpan GetTotalTimeLen(List<TimeSegment> segList)
        {
            TimeSegmentList list = new TimeSegmentList(segList);
            return list.GetTotalTimeLen();
        }

        public void Position2Time(TimeSpan pos, out TimeSegment timeSeg, out DateTime time)
        {
            timeSeg = null;
            time = DateTime.MinValue;
            if (pos.Ticks <= 0L)
            {
                if (this.segList.Count > 0)
                {
                    time = this.segList[0].BeginTime;
                    timeSeg = this.segList[0];
                }
            }
            else
            {
                TimeSpan span = pos;
                TimeSegment segment = null;
                foreach (TimeSegment segment2 in this.segList)
                {
                    TimeSpan length;
                    if (segment != null)
                    {
                        length = (TimeSpan) (segment2.BeginTime - segment.EndTime);
                        if (length.Ticks > 0L)
                        {
                            if (span > length)
                            {
                                span -= length;
                            }
                            else
                            {
                                timeSeg = segment;
                                time = segment.EndTime + span;
                                return;
                            }
                        }
                    }
                    length = segment2.Length;
                    if (span > length)
                    {
                        span -= length;
                    }
                    else
                    {
                        timeSeg = segment2;
                        time = segment2.BeginTime + span;
                        return;
                    }
                    segment = segment2;
                }
                if (segment != null)
                {
                    timeSeg = segment;
                    time = segment.EndTime + span;
                }
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.segList.GetEnumerator();
        }

        public TimeSpan Time2Position(DateTime time)
        {
            TimeSegment segment = null;
            TimeSpan span = new TimeSpan();
            foreach (TimeSegment segment2 in this.segList)
            {
                if (segment != null)
                {
                    TimeSpan span2 = (TimeSpan) (segment2.BeginTime - segment.EndTime);
                    if (span2.Ticks > 0L)
                    {
                        if ((time > segment.EndTime) && (time < segment2.BeginTime))
                        {
                            return (span + (time - segment.EndTime));
                        }
                        span += span2;
                    }
                }
                if (time > segment2.EndTime)
                {
                    span += segment2.Length;
                }
                else
                {
                    if ((time >= segment2.BeginTime) && (time <= segment2.EndTime))
                    {
                        return (span + (time - segment2.BeginTime));
                    }
                    return span;
                }
                segment = segment2;
            }
            if (segment != null)
            {
                span += time - segment.EndTime;
            }
            return span;
        }

        public TimeSpan Time2Position(TimeSegment timeSeg, DateTime time)
        {
            TimeSegment segment = null;
            TimeSpan span = new TimeSpan();
            foreach (TimeSegment segment2 in this.segList)
            {
                if (segment != null)
                {
                    TimeSpan span2 = (TimeSpan) (segment2.BeginTime - segment.EndTime);
                    if (span2.Ticks > 0L)
                    {
                        span += span2;
                    }
                }
                if (timeSeg == segment2)
                {
                    TimeSpan span3 = (TimeSpan) (time - segment2.BeginTime);
                    span3 = (span3.Ticks > 0L) ? span3 : new TimeSpan(0L);
                    return (span + span3);
                }
                segment = segment2;
                span += segment2.Length;
            }
            if ((segment != null) && (time > segment.EndTime))
            {
                span += time - segment.EndTime;
            }
            return span;
        }

        public List<TimeSpan> Time2Positions(DateTime time)
        {
            TimeSegment segment = null;
            List<TimeSpan> list = new List<TimeSpan>();
            TimeSpan span = new TimeSpan();
            TimeSpan item = new TimeSpan();
            foreach (TimeSegment segment2 in this.segList)
            {
                if (segment != null)
                {
                    if ((time > segment.EndTime) && (time < segment2.BeginTime))
                    {
                        item = span + (time - segment.EndTime);
                        list.Add(item);
                    }
                    TimeSpan span3 = (TimeSpan) (segment2.BeginTime - segment.EndTime);
                    if (span3.Ticks > 0L)
                    {
                        span += span3;
                    }
                }
                if ((time >= segment2.BeginTime) && (time <= segment2.EndTime))
                {
                    item = span + (time - segment2.BeginTime);
                    list.Add(item);
                }
                segment = segment2;
                span += segment2.Length;
            }
            if ((segment != null) && (time > segment.EndTime))
            {
                item = span + (time - segment.EndTime);
                list.Add(item);
            }
            return list;
        }

        public int Count
        {
            get
            {
                return this.segList.Count;
            }
        }

        public TimeSegment this[int index]
        {
            get
            {
                return this.segList[index];
            }
            set
            {
                this.segList[index] = value;
            }
        }

        public List<TimeSegment> SegmentList
        {
            get
            {
                return this.segList;
            }
        }
    }
}

